package org.jsrml.common.persistence.web;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.persistence.Id;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.proxy.HibernateProxy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.serializer.ValueFilter;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;


@Configuration
public class FastJsonHttpConfig extends WebMvcConfigurerAdapter{
	
	@Bean
    public FastJsonHttpMessageConverter fastJsonHttpMessageConverter() {
        FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();

        /*QuoteFieldNames———-输出key时是否使用双引号,默认为true 
        WriteMapNullValue——–是否输出值为null的字段,默认为false 
        WriteNullNumberAsZero—-数值字段如果为null,输出为0,而非null 
        WriteNullListAsEmpty—–List字段如果为null,输出为[],而非null 
        WriteNullStringAsEmpty—字符类型字段如果为null,输出为”“,而非null 
        WriteNullBooleanAsFalse–Boolean字段如果为null,输出为false,而非null*/
        
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        fastJsonConfig.setSerializerFeatures(
                //SerializerFeature.PrettyFormat,
               // SerializerFeature.WriteClassName,//输出类名字
                //SerializerFeature.WriteMapNullValue
               // SerializerFeature.WriteNullStringAsEmpty,
               SerializerFeature.DisableCircularReferenceDetect
        );
        ValueFilter valueFilter = new ValueFilter() {
            //o 是class
            //s 是key值
            //o1 是value值
            public Object process(Object o, String s, Object o1) {
                if (null == o1){
                    return null;
                }
                else if(o1 instanceof HibernateProxy){
                	return createInitializeObject(o1);
                }
                return o1;
            }
        };
        fastJsonConfig.setSerializeFilters(valueFilter);
        converter.setFastJsonConfig(fastJsonConfig);
        List<MediaType> supportedMediaTypes = new ArrayList<MediaType>();
        //supportedMediaTypes.add(new MediaType("text", "plain"));
        supportedMediaTypes.add(new MediaType("application", "json"));
        converter.setSupportedMediaTypes(supportedMediaTypes);
        
        return converter;
    }

	/**
	 * 获取有@Id注解的Entity属性
	 * 
	 * @param clazz
	 * @return
	 */
	private static Field getEntityIdField(Class<?> clazz) {
		Class<?> currentClazz = clazz;
		while (currentClazz != Object.class) {
			try {
				Field[] fields = currentClazz.getDeclaredFields();
				for (Field field : fields) {
					if (field.getAnnotation(Id.class) != null) {
						return field;
					}
				}
			} catch (Exception e) { }
			currentClazz = currentClazz.getSuperclass();
		}
		return null;
	}

	/**
	 * 创建延迟加载的对象
	 * 
	 * @param obj
	 * @return
	 */
	private static Object createInitializeObject(Object obj) {
		if (obj instanceof HibernateProxy) {
			HibernateProxy proxy = (HibernateProxy) obj;
			Serializable id = proxy.getHibernateLazyInitializer().getIdentifier();
			if (id == null) {
				return null;
			}
			try {
				Class<?> entityClass = proxy.getHibernateLazyInitializer().getPersistentClass();
				Field idField = getEntityIdField(entityClass);
				if (idField != null) {
					Object entity = entityClass.newInstance();
					idField.setAccessible(true);
					idField.set(entity, id);
					return entity;
				}
			} catch (Exception e1) { }
			return null;
		} else if (obj instanceof PersistentCollection) {
			if (obj instanceof List) {
				return new ArrayList<Object>();
			} else if (obj instanceof Map) {
				return new HashMap<Object, Object>();
			} else if (obj instanceof Set) {
				return new HashSet<Object>();
			}
			return null;
		}
		return obj;
	}
	
	
	
	@Override
	public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
	    super.configureMessageConverters(converters);
	    converters.add(fastJsonHttpMessageConverter());
	}
}
